package com.baymax.test.scene.demo

import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.util.Property
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.core.animation.addListener
import androidx.core.graphics.applyCanvas
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.baymax.test.scene.BaseGroupScene
import com.baymax.test.scene.BaseScene
import com.baymax.test.scene.addButton
import com.baymax.test.scene.drawable.DrawableUtils
import com.baymax.test.scene.newFlexContainer
import com.baymax.test.scene.newSceneFlexContainer
import com.bytedance.scene.ktx.replace
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.drawable.ArrayDrawable
import com.facebook.drawee.drawable.ForwardingDrawable
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
import com.facebook.drawee.generic.RootDrawable
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.CloseableBitmap
import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.request.ImageRequest
import com.google.android.flexbox.FlexboxLayout
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.math.ceil


class PicDemo : BaseGroupScene() {

    companion object {
        val IMG1 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/60ae9439c7d244e99241cf135fe8a194.jpg"
        val IMG2 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/2e28b6d738e2470592d4cb4b7d1bb641.jpg"

        val IMG3 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/116fc8c205834f2fba7a60a853b25f81.jpg"

        val IMG4 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/315511414b4f4c1880aa8ea2d9737147.jpg"
    }

    override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): ViewGroup {
        return p1.newSceneFlexContainer {

            val childId = View.generateViewId()
            addButton("demo1") {
                replace(childId, BillingDemo(), "demo")
            }
            addButton("demo2") {
                replace(childId, BilingDemo2(), "demo")
            }
            addButton("photo view") {
                replace(childId, PhotoViewScene(), "demo")
            }
            val child = FrameLayout(context)
            child.id = childId
            addView(
                child,
                FlexboxLayout.LayoutParams.MATCH_PARENT,
                FlexboxLayout.LayoutParams.WRAP_CONTENT
            )
        }
    }


    class BillingDemo : BaseScene() {

        val img1 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/60ae9439c7d244e99241cf135fe8a194.jpg"
        val img2 =
            "http://images.center.bcs.ottcn.com:8080/images/ysten/picture/ndms/cmedge/2024/02/05/2e28b6d738e2470592d4cb4b7d1bb641.jpg"

        override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
            return p1.newSceneFlexContainer {
                setPadding(0, 0, 0, 0)
                background = DrawableUtils.createGradientDrawable(Color.RED, 2)

                val drawable: ShutterDrawable = ShutterDrawable(null)
                val imgId = View.generateViewId()
                val newImg = newImg(img1, drawable).apply { id = imgId }
                val back = newImg(img2, null)
                val fr = FrameLayout(context)
                fr.addView(back)
                fr.addView(newImg)
//                drawable.setDrawable(newImg.drawable)
//                val place = View(context)
//                place.background = drawable


                this.newFlexContainer {
                    setPadding(0, 0, 0, 0)
                    addButton("start demo1") {
                        Log.d(TAG, "onCreateView: $newImg")
                        drawable.start()
                    }
                    addButton("DST_IN") {
                        drawable.mMode = PorterDuff.Mode.DST_IN
                    }
                    addButton("DST_OUT") {
                        drawable.mMode = PorterDuff.Mode.DST_OUT
                    }
                    addButton("DST") {
                        drawable.mMode = PorterDuff.Mode.DST
                    }
                    addButton("DST_ATOP") {
                        drawable.mMode = PorterDuff.Mode.DST_ATOP
                    }
                    addButton("DST_OVER") {
                        drawable.mMode = PorterDuff.Mode.DST_OVER
                    }
                    addButton("SRC") {
                        drawable.mMode = PorterDuff.Mode.SRC
                    }
                    addButton("SRC_IN") {
                        drawable.mMode = PorterDuff.Mode.SRC_IN
                    }
                    addButton("SRC_OUT") {
                        drawable.mMode = PorterDuff.Mode.SRC_OUT
                    }
                    addButton("SRC_ATOP") {
                        drawable.mMode = PorterDuff.Mode.SRC_ATOP
                    }
                    addButton("SRC_OVER") {
                        drawable.mMode = PorterDuff.Mode.SRC_OVER
                    }
                    addButton("CLEAR") {
                        drawable.mMode = PorterDuff.Mode.CLEAR
                    }

                }

                addView(fr, 300, 300)
//                addView(place , 300 ,300)
            }
        }

        private fun newImg(
            url: String,
            shutterDrawable: ShutterDrawable? = null
        ): SimpleDraweeView {

            return SimpleDraweeView(
                requireSceneContext(),
                GenericDraweeHierarchyBuilder.newInstance(resources)
                    .build().apply {
                    }
            ).apply {

                val req = ImageRequest.fromUri(url)
                controller = Fresco.newDraweeControllerBuilder()
                    .setControllerListener(object : BaseControllerListener<ImageInfo>() {
                        override fun onFinalImageSet(
                            id: String?,
                            imageInfo: ImageInfo?,
                            animatable: Animatable?
                        ) {
                            super.onFinalImageSet(id, imageInfo, animatable)
                            Log.d(TAG, "onFinalImageSet: $id ,$imageInfo")
                            if (imageInfo is CloseableBitmap) {
//                                shutterDrawable.mBitmap = imageInfo
                            }

                            launch {
                                if (shutterDrawable != null) {
                                    val img = this@apply
                                    Log.d(TAG, "onFinalImageSet: ${img.hierarchy}")
                                    val arrayDrawable =
                                        (img.hierarchy.topLevelDrawable as RootDrawable).drawable as
                                                ArrayDrawable
                                    val actual = arrayDrawable.getDrawable(2)
                                    shutterDrawable.setDrawable(actual)
                                    arrayDrawable.setDrawable(2, shutterDrawable)
                                }

                            }
                        }
                    })
                    .setOldController(controller)
                    .setImageRequest(req)
                    .build()


            }
        }
    }

    class ShutterDrawable(drawable: Drawable?) : ForwardingDrawable(drawable) {

        // 设置位图对象
        var mOriention = LinearLayout.HORIZONTAL
        var mLeafCount = 5
        var mRatio = 100
        val mPaint = Paint()
        var mMode = PorterDuff.Mode.DST
        override fun draw(canvas: Canvas) {
            val width: Int = bounds.width()
            val height: Int = bounds.height()

            // 清空画布
            canvas.drawColor(Color.TRANSPARENT)

            // 创建一个遮罩位图
            val mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)


            // 创建一个遮罩画布
            val canvasMask = Canvas(mask)
            for (i in 0 until mLeafCount) {
                if (mOriention == LinearLayout.HORIZONTAL) { // 水平方向
                    val column_width = ceil(width * 1f / mLeafCount).toInt()
                    val left = column_width * i
                    val right: Int = left + column_width * mRatio / 100
                    // 在遮罩画布上绘制各矩形叶片
                    canvasMask.drawRect(
                        left.toFloat(),
                        0f,
                        right.toFloat(),
                        height.toFloat(),
                        mPaint
                    )
                } else { // 垂直方向
                    val row_height = ceil(height * 1f / mLeafCount).toInt()
                    val top = row_height * i
                    val bottom: Int = top + row_height * mRatio / 100
                    // 在遮罩画布上绘制各矩形叶片
                    canvasMask.drawRect(
                        0f,
                        top.toFloat(),
                        width.toFloat(),
                        bottom.toFloat(),
                        mPaint
                    )
                }
            }

            // 设置离屏缓存
            val saveLayer = canvas.saveLayer(
                0f,
                0f,
                width.toFloat(),
                height.toFloat(),
                null,
                Canvas.ALL_SAVE_FLAG
            )


            // 绘制目标图像
            super.draw(canvas)

            // 设置混合模式（只在源图像和目标图像相交的地方绘制目标图像）
            mPaint.setXfermode(PorterDuffXfermode(mMode))

            // 再绘制源图像的遮罩
            canvas.drawBitmap(mask, 0f, 0f, mPaint)

            // 还原混合模式
            mPaint.setXfermode(null)

            // 还原画布
            canvas.restoreToCount(saveLayer)

        }

        override fun setAlpha(alpha: Int) {
        }

        override fun setColorFilter(colorFilter: ColorFilter?) {
        }

        override fun getOpacity(): Int = PixelFormat.UNKNOWN
        val p = object : Property<ShutterDrawable, Int>(Int::class.java, "mRation") {
            override fun get(`object`: ShutterDrawable?): Int {
                return `object`?.mRatio ?: 0
            }

            override fun set(`object`: ShutterDrawable?, value: Int?) {
                `object`?.mRatio = value ?: 0
            }
        }

        fun start() {
            val anim = ObjectAnimator.ofInt(this, p, 0, 100)
            anim.addUpdateListener { invalidateSelf() }
            anim.setDuration(3000) // 设置动画的播放时长
            anim.start() // 开始播放属性动画
        }

    }


    class BilingDemo2 : BaseScene() {


        override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
            return p1.newSceneFlexContainer {
                setPadding(0, 0, 0, 0)
                background = DrawableUtils.createGradientDrawable(Color.RED, 2)

                val urls = listOf(IMG1, IMG2, IMG3, IMG4)
                val shutterView = ShutterView(context, urls)

                urls.forEach {
                    Fresco.getImagePipeline()
                        .prefetchToBitmapCache(ImageRequest.fromUri(Uri.parse(it)), this)
                }
                this.newFlexContainer {
                    setPadding(0, 0, 0, 0)
                    addButton("start demo2") {
                        Log.d(TAG, "onCreateView: $shutterView ")
                        shutterView.switch()
                    }
//                    addButton("DST_IN") {
//                        shutterView.mMode = PorterDuff.Mode.DST_IN
//                    }
//                    addButton("DST_OUT") {
//                        shutterView.mMode = PorterDuff.Mode.DST_OUT
//                    }
//                    addButton("DST") {
//                        shutterView.mMode = PorterDuff.Mode.DST
//                    }
//                    addButton("DST_ATOP") {
//                        shutterView.mMode = PorterDuff.Mode.DST_ATOP
//                    }
//                    addButton("DST_OVER") {
//                        shutterView.mMode = PorterDuff.Mode.DST_OVER
//                    }

//                    addButton("SRC") {
//                        shutterView.mMode = PorterDuff.Mode.SRC
//                    }
//                    addButton("SRC_IN") {
//                        shutterView.mMode = PorterDuff.Mode.SRC_IN
//                    }
//                    addButton("SRC_OUT") {
//                        shutterView.mMode = PorterDuff.Mode.SRC_OUT
//                    }
//                    addButton("SRC_ATOP") {
//                        shutterView.mMode = PorterDuff.Mode.SRC_ATOP
//                    }
//
//                    addButton("SRC_OVER") {
//                        shutterView.mMode = PorterDuff.Mode.SRC_OVER
//                    }
//                    addButton("CLEAR") {
//                        shutterView.mMode = PorterDuff.Mode.CLEAR
//                    }
                }

                addView(shutterView, 300, 300)
            }
        }

    }

    class ShutterView(context: Context, private val urls: List<String>) : FrameLayout(context),
        CoroutineScope by MainScope() {
        class Switcher(private val urls: List<String>) {
            var _current = 0

            val current get() = urls.getOrNull(_current).orEmpty()

            val next get() = urls.getOrNull(_current.inc()) ?: urls.firstOrNull().orEmpty()

            fun increase() {
                _current = _current.inc()
                if (_current >= urls.size) {
                    _current = 0
                }
            }

        }


        val switcher = Switcher(urls)

        val main = SimpleDraweeView(context)
        val slave = SimpleDraweeView(context)

        // 设置位图对象
        var mOriention = LinearLayout.VERTICAL
        var mLeafCount = 5
        var mRatio = 100
        val mPaint = Paint()
        var switch = false

        init {
            addView(slave, -1, -1)
            addView(main, -1, -1)
        }

        fun switch() {
            main.setImageURI(switcher.current)
            slave.setImageURI(switcher.next)
            launch {
                delay(3000)
                start()
            }
        }

        val drawRect = Rect()


        override fun dispatchDraw(canvas: Canvas) {
            if (!switch) {
                return super.dispatchDraw(canvas)
            }
            val width: Int = width
            val height: Int = height

            // 清空画布
            canvas.drawColor(Color.TRANSPARENT)

            // 设置离屏缓存
            val saveLayer = canvas.save()


            // 绘制底部图像
            slave.draw(canvas)
            // 设置混合模式（只在源图像和目标图像相交的地方绘制目标图像）
//            mPaint.setXfermode(PorterDuffXfermode(mMode))

            val mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).applyCanvas {
                translate(-scrollX.toFloat(), -scrollY.toFloat())
                main.draw(this)
            }
            // 再绘制源图像的遮罩
            for (i in 0 until mLeafCount) {
                if (mOriention == LinearLayout.HORIZONTAL) { // 水平方向
                    val column_width = ceil(width * 1f / mLeafCount).toInt()
                    val left = column_width * i
                    val right: Int = left + column_width * mRatio / 100
                    drawRect.set(left, 0, right, height)
                    // 在遮罩画布上绘制各矩形叶片
                    canvas.drawBitmap(
                        mask,
                        drawRect,
                        drawRect,
                        mPaint
                    )
                } else { // 垂直方向
                    val row_height = ceil(height * 1f / mLeafCount).toInt()
                    val top = row_height * i
                    val bottom: Int = top + row_height * mRatio / 100
                    drawRect.set(0, top, width, bottom)
                    canvas.drawBitmap(
                        mask,
                        drawRect,
                        drawRect,
                        mPaint
                    )
                    // 在遮罩画布上绘制各矩形叶片
                }
            }


            // 还原画布
            canvas.restoreToCount(saveLayer)

        }

        override fun onDrawForeground(canvas: Canvas) {
            super.onDrawForeground(canvas)
            canvas.drawText(switcher._current.toString(), 20f, 20f, mPaint)
        }

        val p = object : Property<ShutterView, Int>(Int::class.java, "mRation") {
            override fun get(`object`: ShutterView?): Int {
                return `object`?.mRatio ?: 0
            }

            override fun set(`object`: ShutterView?, value: Int?) {
                `object`?.mRatio = 100 - (value ?: 0)
            }
        }

        fun start() {

            val anim = ObjectAnimator.ofInt(this, p, 0, 100)
            anim.addUpdateListener { invalidate() }
            anim.addListener(onEnd = {
                switcher.increase()
                switch()
                switch = false


            }, onStart = { switch = true })
            anim.setDuration(3000) // 设置动画的播放时长
            anim.start() // 开始播放属性动画
        }

        fun startAnim2() {
            val anim = ObjectAnimator.ofInt(this, p, 100, 0)
            anim.addUpdateListener { invalidate() }
            anim.addListener(onEnd = {
                switcher.increase()
                switch()
                switch = false


            }, onStart = { switch = true })
            anim.setDuration(3000) // 设置动画的播放时长
            anim.start() // 开始播放属性动画
        }


        override fun onDetachedFromWindow() {
            super.onDetachedFromWindow()
            cancel()
        }
    }

    class PhotoViewScene() : BaseScene() {
        override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
            return p1.newSceneFlexContainer {

                setPadding(0, 0, 0, 0)
                background = DrawableUtils.createGradientDrawable(Color.RED, 2)
                val urls = listOf(IMG1, IMG2, IMG3, IMG4)

                val photo = PhotoView(context)
                photo.setDataUrls(urls)

                addButton("setDatas") {
                    photo.setDataUrls(urls)
                }
                addButton("shutter-x") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_SHUTTER_HORIZONTAL)
                }
                addButton("shutter-y") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_SHUTTER_VERTICAL)
                }
                addButton("curtain-x") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_CURTAIN_X)
                }
                addButton("curtain-y") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_CURTAIN_Y)
                }
                addButton("translation-👆") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_TRANSLATION_DOWN_UP)
                }
                addButton("translation-👇") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_TRANSLATION_UP_DOWN)
                }
                addButton("rect ") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_RECT)
                }
                addButton("circle ") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_CIRCLE)
                }
                addButton("random all") {
                    photo.setDrawer(PhotoView.AnimationMode.ANIMATION_RANDOM)
                }
                addButton("cancel") {
                    photo.pause()
                }
                addView(photo, 300, 300)

                this@PhotoViewScene.lifecycle.addObserver(object : DefaultLifecycleObserver {
                    override fun onDestroy(owner: LifecycleOwner) {
                        super.onDestroy(owner)
                        photo.onDestroy()
                    }
                })
            }
        }

    }


}